package io.github.bigbird0101.youyishi.code;

import cn.hutool.extra.spring.SpringUtil;
import io.github.bigbird0101.youyishi.code.event.*;
import lombok.extern.slf4j.Slf4j;
import io.github.bigbird0101.youyishi.code.compile.CodeMetadata;
import org.fpp.youyishi.code.event.*;

import java.util.Collections;
import java.util.List;

/**
 * @author m15179835326@163.com
 * @date 2023-05-12 15:03
 */
@Slf4j
public abstract class AbstractCodeLifecycle implements CodeLifecycle {

    @Override
    public List<CodeContent<?>> generate(GenerateCodeParam generateCodeParam) {
        try {
            sendEvent(new GenerateBeforeEvent(generateCodeParam));
            List<CodeContent<?>> codeContents = doGenerate(generateCodeParam);
            sendEvent(new GenerateSuccessEvent(codeContents,generateCodeParam));
            return codeContents;
        }catch (Exception exception){
            log.error("生成代码失败",exception);
            sendEvent(new GenerateFailedEvent(generateCodeParam,exception));
        }
        return Collections.emptyList();
    }

    /**
     * 去生成代码
     * @param generateCodeParam 生成参数
     * @return 代码
     */
    protected abstract List<CodeContent<?>> doGenerate(GenerateCodeParam generateCodeParam);

    @Override
    public List<CodeMetadata> compile(List<CodeContent<?>> codeContents) {
        try {
            sendEvent(new CompileBeforeEvent(codeContents));
            List<CodeMetadata> codeMetadataList = doCompile(codeContents);
            doSendCompileSuccessEvent(codeContents, codeMetadataList);
            return codeMetadataList;
        }catch (Exception exception){
            log.error("编译代码失败",exception);
            sendEvent(new CompileFailedEvent(codeContents,exception));
        }
        return Collections.emptyList();
    }

    protected void doSendCompileSuccessEvent(List<CodeContent<?>> codeContents, List<CodeMetadata> codeMetadataList) {
        sendEvent(new CompileSuccessEvent(codeContents, codeMetadataList));
    }

    /**
     * 去编译代码
     * @param codeContents 代码
     * @return 编译后代码
     */
    protected abstract List<CodeMetadata> doCompile(List<CodeContent<?>> codeContents);


    @Override
    public void run(List<CodeMetadata> codeMetadatas) {
        try {
            sendEvent(new RunBeforeEvent(codeMetadatas));
            doRun(codeMetadatas);
            doSendRunSuccessEvent(codeMetadatas);
        }catch (Exception exception){
            log.error("运行代码失败",exception);
            sendEvent(new RunFailedEvent(codeMetadatas,exception));
        }
    }

    protected void doSendRunSuccessEvent(List<CodeMetadata> codeMetadatas) {
        sendEvent(new RunSuccessEvent(codeMetadatas));
    }

    /**
     * 去运行代码
     * @param codeMetadatas 代码元数据
     */
    protected abstract void doRun(List<CodeMetadata> codeMetadatas);

    @Override
    public void destroy(List<CodeContent<?>> codeContents) {
        try {
            sendEvent(new DestroyBeforeEvent(codeContents));
            doDestroy(codeContents);
            sendEvent(new DestroySuccessEvent(codeContents));
        }catch (Exception exception){
            log.error("销毁代码失败",exception);
            sendEvent(new DestroyFailedEvent(codeContents,exception));
        }
    }

    /**
     * 去销毁代码
     * @param codeContents 代码内容
     */
    protected abstract void doDestroy(List<CodeContent<?>> codeContents);

    public void sendEvent(CodeEvent codeEvent){
        try{
            if(null==codeEvent){
                applicationContext= SpringUtil.getApplicationContext();
            }
            applicationContext.publishEvent(codeEvent);
        }catch (Exception exception){
            log.error(String.format("%s事件发送失败",codeEvent.getClass().getSimpleName()),exception);
        }
    }

}
